#include "mannasettings.h"
#include "meditor.h"
#include "misc.h"
#include <qscintilla.h>
#include <QCoreApplication>
#include <QApplication>
#include <QTextCodec>
#include <QMessageBox>
#include <QDir>

QString MannaSettings::m_ProgName;
QString MannaSettings::m_ProgVersion;
MannaSettings* MannaSettings::m_settings = NULL;
QHash<QString,QsciLexer*> MannaSettings::m_lexers;
QHash<QString,QsciAPIs*> MannaSettings::m_APIs;

const QString SettingsPath = "Settings";

MannaSettings::MannaSettings( QObject* o )
    : QSettings( QDir::toNativeSeparators( getMannaSettingFile()), QSettings::IniFormat, o )
{
    beginGroup( m_ProgName + "-" + m_ProgVersion );
}

MannaSettings::~MannaSettings()
{
    endGroup();
}

void MannaSettings::setIniInformations( const QString& pName, const QString& pVersion )
{
    m_ProgName = pName;
    m_ProgVersion = pVersion;
}

MannaSettings *MannaSettings::getMannaSettings()
{
    if (!m_settings) {
        m_settings = new MannaSettings(qApp);
    }
    return m_settings;
}

void MannaSettings::prepareAPIs()
{
    // check lexers & apis
    if ( m_lexers.isEmpty() || m_APIs.isEmpty() )
    {
        // free hashes
        qDeleteAll( m_lexers );
        m_lexers.clear();
        qDeleteAll( m_APIs );
        m_APIs.clear();
    }
    //
    foreach ( QString ln, optMannaSettings::availableLanguages() )
    {
        QsciLexer* l = lexerForLanguage( ln );
        QsciAPIs* a = apisForLexer( l );
        // clear raw api
        a->clear();
        // load prepared files
        QStringList list = value( QString( "SourceAPIs/" ).append( ln ) ).toStringList();
        if (list.count() == 0) {
            list = optMannaSettings::defaultAPIsForLanguages(ln);
        }
        foreach ( QString f, list )
        {
            if ( !a->load( QDir::isRelativePath( f ) ? qApp->applicationDirPath().append( "/%1" ).arg( f ) : f ) )
                qWarning("%s", (const char *)QObject::tr( "An error occured when loading api file:\n%1" ).arg( f ).toLocal8Bit());
        }
        // start prepare for apis
        a->prepare();
    }
}

QsciAPIs* MannaSettings::apisForLexer( QsciLexer* l )
{
    // cancel if no lexer
    if ( !l )
        return 0;
    // check if apis already exists
    if ( !m_APIs.contains( l->language() ) )
    {
        // create apis
        QsciAPIs* a = new QsciAPIs( l );
        // store global apis
        m_APIs[l->language()] = a;
    }
    // return apis
    return m_APIs.value( l->language() );
}

QString MannaSettings::languageForFileName( const QString& s )
{
    QsciLexer* l = lexerForFileName( s );
    return l ? QString( l->language() ) : QString();
}

QsciLexer* MannaSettings::lexerForFileName( const QString& s )
{
    // get suffixes
    QHash<QString, QStringList> l = optMannaSettings::availableFilesSuffixes();
    // check suffixe
    foreach ( QString k, l.keys() )
        if ( QDir::match( l.value( k ), s ) )
            return lexerForLanguage( k );
    return 0;
}

QsciLexer* MannaSettings::lexerForLanguage( const QString& s )
{
    if ( m_lexers.keys().contains( s ) )
        return m_lexers.value( s );
    QsciLexer *l = optMannaSettings::getLexerByLanguage(s);
    // init lexer getMannaSettings
    if ( l ) {
        // add lexer to global lexers hash
        m_lexers[l->language()] = l;
        // read getMannaSettings
        MannaSettings* ss = getMannaSettings();
        l->readSettings( *ss, qPrintable( MannaSettings::scintillaSettingsPath() ) );
        // set apis
        l->setAPIs( apisForLexer( l ) );
    }
    // return lexer
    return l;
}

const QString MannaSettings::settingsPath()
{
    return "/Settings";
}

const QString MannaSettings::scintillaSettingsPath()
{
    return "/Scintilla";
}

void MannaSettings::applySettings()
{
    // apply lexers properties
    foreach ( QsciLexer* l, m_lexers.values() )
    {
        // refresh properties
        l->readSettings( *this, qPrintable( MannaSettings::scintillaSettingsPath() ) );
        // refresh default pen/paper if needed
        if ( optMannaSettings::defaultDocumentColours() )
        {
            l->setDefaultColor( optMannaSettings::defaultDocumentPen() );
            l->setDefaultPaper( optMannaSettings::defaultDocumentPaper() );
        }
        // reload apis
        if ( l->apis() )
            foreach ( QString s, value( QString( "SourceAPIs/" ).append( l->language() ) ).toStringList() )
                ((QsciAPIs*)l->apis())->loadPrepared( s );
    }
}

void MannaSettings::compilerPath(QString &gcc, QString &fpc, QString &suffix, bool &show/* = false */)
{
    beginGroup("ExternTools");

#ifdef Q_OS_WIN
    suffix = ".exe";

    gcc = qApp->applicationDirPath();
    gcc = gcc.left(gcc.length()) + "/MinGW/bin";
    gcc = value("gcc_path", QVariant(gcc)).toString();
    fpc = value("fpc_path", QVariant("C:/FPC/2.2.2/bin/i386-win32")).toString();
#else
    gcc = value("gcc_path", QVariant("/usr/bin")).toString();
    fpc = value("fpc_path", QVariant("/usr/bin")).toString();
#endif

    show = (value("show_flag","false")!="false");

    endGroup();
}

/* optMannaSettings */
QsciLexer * optMannaSettings::getLexerByLanguage(const QString &s)
{
    // get language
    const QString ln = s.toLower();
    // lexer
    QsciLexer* l = 0;
    // init lexer
    if ( ln == "bash" )
        l = new QsciLexerBash( QApplication::instance() );
    else if ( ln == "batch" )
        l = new QsciLexerBatch( QApplication::instance() );
    else if ( ln == "c#" )
        l = new QsciLexerCSharp( QApplication::instance() );
    else if ( ln == "c++" )
        l = new QsciLexerCPP( QApplication::instance() );
    else if ( ln == "pascal" )
        l = new QsciLexerPascal( QApplication::instance() );
    else if ( ln == "cmake" )
        l = new QsciLexerCMake( QApplication::instance() );
    else if ( ln == "css" )
        l = new QsciLexerCSS( QApplication::instance() );
    else if ( ln == "d" )
        l = new QsciLexerD( QApplication::instance() );
    else if ( ln == "diff" )
        l = new QsciLexerDiff( QApplication::instance() );
    else if ( ln == "html" )
        l = new QsciLexerHTML( QApplication::instance() );
    else if ( ln == "idl" )
        l = new QsciLexerIDL( QApplication::instance() );
    else if ( ln == "java" )
        l = new QsciLexerJava( QApplication::instance() );
    else if ( ln == "javascript" )
        l = new QsciLexerJavaScript( QApplication::instance() );
    else if ( ln == "lua" )
        l = new QsciLexerLua( QApplication::instance() );
    else if ( ln == "makefile" )
        l = new QsciLexerMakefile( QApplication::instance() );
    else if ( ln == "pov" )
        l = new QsciLexerPOV( QApplication::instance() );
    else if ( ln == "perl" )
        l = new QsciLexerPerl( QApplication::instance() );
    else if ( ln == "properties" )
        l = new QsciLexerProperties( QApplication::instance() );
    else if ( ln == "python" )
        l = new QsciLexerPython( QApplication::instance() );
    else if ( ln == "ruby" )
        l = new QsciLexerRuby( QApplication::instance() );
    else if ( ln == "sql" )
        l = new QsciLexerSQL( QApplication::instance() );
    else if ( ln == "tcl" )
        l = new QsciLexerTCL( QApplication::instance() );
    else if ( ln == "tex" )
        l = new QsciLexerTeX( QApplication::instance() );
    else if ( ln == "vhdl" )
        l = new QsciLexerVHDL( QApplication::instance() );

    return l;
}

bool optMannaSettings::setLexerProperty( const QString& s, QsciLexer* l, const QVariant& v )
{
    // cancel no property, no lexer or if variant is not valid
    if ( !l || s.trimmed().isEmpty() || !v.isValid() )
        return false;
    // if bool
    if ( v.type() == QVariant::Bool )
        return QMetaObject::invokeMethod( l, qPrintable( s ), Q_ARG( bool, v.toBool() ) );
    // if int
    else if ( v.type() == QVariant::Int )
        return QMetaObject::invokeMethod( l, qPrintable( s ), Q_ARG( QsciLexerPython::IndentationWarning, (QsciLexerPython::IndentationWarning)v.toInt() ) );
    // return default value
    return false;
}

const QVariant optMannaSettings::lexerProperty( const QString& s, QsciLexer* l )
{
    // if no member or lexer return null variant
    if ( !l || s.isEmpty() )
        return QVariant();
    // get language
    const QString lng = QString( l->language() );
    // checking property
    if ( s == "foldComments" )
    {
        if ( lng == "Bash" )
            return qobject_cast<QsciLexerBash*>( l )->foldComments();
        else if ( lng == "CSS" )
            return qobject_cast<QsciLexerCSS*>( l )->foldComments();
        else if ( lng == "D" )
            return qobject_cast<QsciLexerD*>( l )->foldComments();
        else if ( lng == "Perl" )
            return qobject_cast<QsciLexerPerl*>( l )->foldComments();
        else if ( lng == "POV" )
            return qobject_cast<QsciLexerPOV*>( l )->foldComments();
        else if ( lng == "Python" )
            return qobject_cast<QsciLexerPython*>( l )->foldComments();
        else if ( lng == "SQL" )
            return qobject_cast<QsciLexerSQL*>( l )->foldComments();
        else if ( lng == "VHDL" )
            return qobject_cast<QsciLexerVHDL*>( l )->foldComments();
        else if ( lng == "JavaScript" )
            return qobject_cast<QsciLexerJavaScript*>( l )->foldComments();
        else if ( lng == "Java" )
            return qobject_cast<QsciLexerJava*>( l )->foldComments();
        else if ( lng == "C#" )
            return qobject_cast<QsciLexerCSharp*>( l )->foldComments();
        else if ( lng == "C++" )
            return qobject_cast<QsciLexerCPP*>( l )->foldComments();
    }
    else if ( s == "foldCompact" )
    {
        if ( lng == "Bash" )
            return qobject_cast<QsciLexerBash*>( l )->foldCompact();
        else if ( lng == "CSS" )
            return qobject_cast<QsciLexerCSS*>( l )->foldCompact();
        else if ( lng == "D" )
            return qobject_cast<QsciLexerD*>( l )->foldCompact();
        else if ( lng == "HTML" )
            return qobject_cast<QsciLexerHTML*>( l )->foldCompact();
        else if ( lng == "Lua" )
            return qobject_cast<QsciLexerLua*>( l )->foldCompact();
        else if ( lng == "Perl" )
            return qobject_cast<QsciLexerPerl*>( l )->foldCompact();
        else if ( lng == "POV" )
            return qobject_cast<QsciLexerPOV*>( l )->foldCompact();
        else if ( lng == "Properties" )
            return qobject_cast<QsciLexerProperties*>( l )->foldCompact();
        else if ( lng == "SQL" )
            return qobject_cast<QsciLexerSQL*>( l )->foldCompact();
        else if ( lng == "VHDL" )
            return qobject_cast<QsciLexerVHDL*>( l )->foldCompact();
        else if ( lng == "JavaScript" )
            return qobject_cast<QsciLexerJavaScript*>( l )->foldCompact();
        else if ( lng == "Java" )
            return qobject_cast<QsciLexerJava*>( l )->foldCompact();
        else if ( lng == "C#" )
            return qobject_cast<QsciLexerCSharp*>( l )->foldCompact();
        else if ( lng == "C++" )
            return qobject_cast<QsciLexerCPP*>( l )->foldCompact();
//        else if ( lng == "TCL" )
//            return qobject_cast<QsciLexerTCL*>( l )->foldCompact();
    }
    else if ( s == "foldQuotes" )
    {
        if ( lng == "Python" )
            return qobject_cast<QsciLexerPython*>( l )->foldQuotes();
    }
    else if ( s == "foldDirectives" )
    {
        if ( lng == "POV" )
            return qobject_cast<QsciLexerPOV*>( l )->foldDirectives();
    }
    else if ( s == "foldAtBegin" )
    {
        if ( lng == "VHDL" )
            return qobject_cast<QsciLexerVHDL*>( l )->foldAtBegin();
    }
    else if ( s == "foldAtParenthesis" )
    {
        if ( lng == "VHDL" )
            return qobject_cast<QsciLexerVHDL*>( l )->foldAtParenthesis();
    }
    else if ( s == "foldAtElse" )
    {
        if ( lng == "CMake" )
            return qobject_cast<QsciLexerCMake*>( l )->foldAtElse();
        else if ( lng == "D" )
            return qobject_cast<QsciLexerD*>( l )->foldAtElse();
        else if ( lng == "VHDL" )
            return qobject_cast<QsciLexerVHDL*>( l )->foldAtElse();
        else if ( lng == "JavaScript" )
            return qobject_cast<QsciLexerJavaScript*>( l )->foldAtElse();
        else if ( lng == "Java" )
            return qobject_cast<QsciLexerJava*>( l )->foldAtElse();
        else if ( lng == "C#" )
            return qobject_cast<QsciLexerCSharp*>( l )->foldAtElse();
        else if ( lng == "C++" )
            return qobject_cast<QsciLexerCPP*>( l )->foldAtElse();
    }
    else if ( s == "foldPreprocessor" )
    {
        if ( lng == "HTML" )
            return qobject_cast<QsciLexerHTML*>( l )->foldPreprocessor();
        else if ( lng == "JavaScript" )
            return qobject_cast<QsciLexerJavaScript*>( l )->foldPreprocessor();
        else if ( lng == "Java" )
            return qobject_cast<QsciLexerJava*>( l )->foldPreprocessor();
        else if ( lng == "C#" )
            return qobject_cast<QsciLexerCSharp*>( l )->foldPreprocessor();
        else if ( lng == "C++" )
            return qobject_cast<QsciLexerCPP*>( l )->foldPreprocessor();
    }
    else if ( s == "stylePreprocessor" )
    {
        if ( lng == "JavaScript" )
            return qobject_cast<QsciLexerJavaScript*>( l )->stylePreprocessor();
        else if ( lng == "Java" )
            return qobject_cast<QsciLexerJava*>( l )->stylePreprocessor();
        else if ( lng == "C#" )
            return qobject_cast<QsciLexerCSharp*>( l )->stylePreprocessor();
        else if ( lng == "C++" )
            return qobject_cast<QsciLexerCPP*>( l )->stylePreprocessor();
    }
    else if ( s == "caseSensitiveTags" )
    {
        if ( lng == "HTML" )
            return qobject_cast<QsciLexerHTML*>( l )->caseSensitiveTags();
    }
    else if ( s == "backslashEscapes" )
    {
        if ( lng == "SQL" )
            return qobject_cast<QsciLexerSQL*>( l )->backslashEscapes();
    }
    else if ( s == "indentationWarning" )
    {
        if ( lng == "Python" )
            return qobject_cast<QsciLexerPython*>( l )->indentationWarning();
    }
    // default return value
    return QVariant();
}

void optMannaSettings::resetLexer( QsciLexer* l )
{
    // cancel if no lexer
    if ( !l )
        return;
#if 0
    // reset lexer settings
    MannaSettings::getMannaSettings()->remove( QString( "%1/%2" ).arg( MannaSettings::scintillaSettingsPath() ).arg( l->language() ) );
    // read default settings
    MannaSettings* ss = MannaSettings::getMannaSettings();
    l->readSettings( *ss, qPrintable( MannaSettings::scintillaSettingsPath() ) );
    // emit changes
    l->refreshProperties();
#else
    QsciLexer *org = getLexerByLanguage(l->language());
    MannaSettings* ss = MannaSettings::getMannaSettings();
    org->writeSettings( *ss, qPrintable( MannaSettings::scintillaSettingsPath() ) );
    delete org;
    l->readSettings( *ss, qPrintable( MannaSettings::scintillaSettingsPath() ) );
    // emit changes
    l->refreshProperties();
#endif
}

const QHash<QString, QStringList> optMannaSettings::defaultLanguagesSuffixes()
{
    // suffixes list
    QHash<QString, QStringList> l;
    // C++
    l["C++"] << "*.c";
    l["C++"] << "*.cc";
    l["C++"] << "*.cpp";
    l["C++"] << "*.cxx";
    l["C++"] << "*.c++";
    l["C++"] << "*.h";
    l["C++"] << "*.hh";
    l["C++"] << "*.hpp";
    l["C++"] << "*.hxx";
    l["C++"] << "*.h++";
    // pascal
    l["pascal"] << "*.pas";
    l["pascal"] << "*.pp";
    // return list
    return l;
}

const QHash<QString, QStringList> optMannaSettings::availableLanguagesSuffixes()
{
    // suffixes list
    QHash<QString, QStringList> l;
    // get settings
    MannaSettings* s = MannaSettings::getMannaSettings();
    // get associations from settings
    s->beginGroup( "LexersAssociations" );
    foreach ( QString k, s->childKeys() )
        l[s->value( k ).toString()] << k;
    s->endGroup();
    // if empty get default suffixes
    if ( l.isEmpty() )
        l = defaultLanguagesSuffixes();
    // return list
    return l;
}

const QStringList optMannaSettings::availableLanguages()
{
    static QStringList l = QStringList() << "C++" << "Pascal";
    return l;
}

const QStringList optMannaSettings::availableTextCodecs()
{
    static QStringList l;
    if ( l.isEmpty() ) {
        foreach ( QByteArray a, QTextCodec::availableCodecs() )
            l << a;
        l.sort();
    }
    return l;
}

const QHash<QString, QStringList> optMannaSettings::availableFilesSuffixes()
{
    // get language suffixes
    QHash<QString, QStringList> l = availableLanguagesSuffixes();
    // return list
    return l;
}

const QStringList optMannaSettings::defaultAPIsForLanguages(const QString &s)
{
    // get language
    const QString ln = s.toLower();
    QStringList list;
    QString apiRoot;
#ifdef    Q_OS_WIN
        apiRoot = QDir(qApp->applicationDirPath()).absolutePath () + "/apis/";
#else
        apiRoot = "/usr/share/apis/";
#endif    // init lexer
    if ( ln == "c++" ) {
        list << apiRoot + "c.api";
        list << apiRoot + "cpp.api";
    } else if ( ln == "pascal" ) {
        list << apiRoot + "pascal.api";
    }
    return list;
}


void optMannaSettings::setAutoSyntaxCheck( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/AutoSyntaxCheck", b );
}

//const bool optMannaSettings::autoSyntaxCheck()
bool optMannaSettings::autoSyntaxCheck()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/AutoSyntaxCheck", false ).toBool();
}

void optMannaSettings::setConvertTabsUponOpen( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/ConvertTabsUponOpen", b );
}

//const bool optMannaSettings::convertTabsUponOpen()
bool optMannaSettings::convertTabsUponOpen()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/ConvertTabsUponOpen", false ).toBool();
}

void optMannaSettings::setCreateBackupUponOpen( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/CreateBackupUponOpen", b );
}

//const bool optMannaSettings::createBackupUponOpen()
bool optMannaSettings::createBackupUponOpen()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/CreateBackupUponOpen", false ).toBool();
}

void optMannaSettings::setAutoEolConversion( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/AutoEolConversion", b );
}

//const bool optMannaSettings::autoEolConversion()
bool optMannaSettings::autoEolConversion()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/AutoEolConversion", true ).toBool();
}

void optMannaSettings::setDefaultEncoding( const QString& s )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/DefaultEncoding", s );
}

const QString optMannaSettings::defaultEncoding()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/DefaultEncoding", "UTF-8" ).toString();
}

void optMannaSettings::setSelectionBackgroundColor( const QColor& c )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/SelectionBackgroundColor", c );
}

const QColor optMannaSettings::selectionBackgroundColor()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/SelectionBackgroundColor", QColor( "#c0c0c0" ) ).value<QColor>();
}

void optMannaSettings::setSelectionForegroundColor( const QColor& c )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/SelectionForegroundColor", c );
}

const QColor optMannaSettings::selectionForegroundColor()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/SelectionForegroundColor", QColor( "#000000" ) ).value<QColor>();
}

void optMannaSettings::setDefaultDocumentColours( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/DefaultDocumentColours", b );
}

//const bool optMannaSettings::defaultDocumentColours()
bool optMannaSettings::defaultDocumentColours()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/DefaultDocumentColours", false ).toBool();
}

void optMannaSettings::setDefaultDocumentPen( const QColor& c )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/DefaultDocumentPen", c );
}

const QColor optMannaSettings::defaultDocumentPen()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/DefaultDocumentPen", QColor( Qt::black ) ).value<QColor>();
}

void optMannaSettings::setDefaultDocumentPaper( const QColor& c )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/DefaultDocumentPaper", c );
}

const QColor optMannaSettings::defaultDocumentPaper()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/DefaultDocumentPaper", QColor( Qt::white ) ).value<QColor>();
}

void optMannaSettings::setAutoCompletionCaseSensitivity( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/AutoCompletionCaseSensitivity", b );
}

//const bool optMannaSettings::autoCompletionCaseSensitivity()
bool optMannaSettings::autoCompletionCaseSensitivity()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/AutoCompletionCaseSensitivity", true ).toBool();
}

void optMannaSettings::setAutoCompletionReplaceWord( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/AutoCompletionReplaceWord", b );
}

//const bool optMannaSettings::autoCompletionReplaceWord()
bool optMannaSettings::autoCompletionReplaceWord()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/AutoCompletionReplaceWord", true ).toBool();
}

void optMannaSettings::setAutoCompletionShowSingle( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/AutoCompletionShowSingle", b );
}

//const bool optMannaSettings::autoCompletionShowSingle()
bool optMannaSettings::autoCompletionShowSingle()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/AutoCompletionShowSingle", false ).toBool();
}

void optMannaSettings::setAutoCompletionSource( QsciScintilla::AutoCompletionSource a )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/AutoCompletionSource", a );
}

//const
QsciScintilla::AutoCompletionSource optMannaSettings::autoCompletionSource()
{
    return (QsciScintilla::AutoCompletionSource)MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/AutoCompletionSource", (int)QsciScintilla::AcsAll ).toInt();
}

void optMannaSettings::setAutoCompletionThreshold( int i )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/AutoCompletionThreshold", i );
}

//const
int optMannaSettings::autoCompletionThreshold()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/AutoCompletionThreshold", 3 ).toInt();
}

void optMannaSettings::setCallTipsBackgroundColor( const QColor& c )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/CallTipsBackgroundColor", c );
}

const QColor optMannaSettings::callTipsBackgroundColor()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/CallTipsBackgroundColor", QColor( "#ffff9b" ) ).value<QColor>();
}

void optMannaSettings::setCallTipsForegroundColor( const QColor& c )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/CallTipsForegroundColor", c );
}

const QColor optMannaSettings::callTipsForegroundColor()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/CallTipsForegroundColor", QColor( "#000000" ) ).value<QColor>();
}

void optMannaSettings::setCallTipsHighlightColor( const QColor& c )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/CallTipsHighlightColor", c );
}

const QColor optMannaSettings::callTipsHighlightColor()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/CallTipsHighlightColor", QColor( "#ff0000" ) ).value<QColor>();
}

void optMannaSettings::setCallTipsStyle( QsciScintilla::CallTipsStyle s )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/CallTipsStyle", s );
}

//const
QsciScintilla::CallTipsStyle optMannaSettings::callTipsStyle()
{
    return (QsciScintilla::CallTipsStyle)MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/CallTipsStyle", (int)QsciScintilla::CallTipsContext ).toInt();
}

void optMannaSettings::setCallTipsVisible( int i )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/CallTipsVisible", i );
}

//const
int optMannaSettings::callTipsVisible()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/CallTipsVisible", -1 ).toInt();
}

void optMannaSettings::setAutoIndent( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/AutoIndent", b );
}

//const
bool optMannaSettings::autoIndent()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/AutoIndent", true ).toBool();
}

void optMannaSettings::setBackspaceUnindents( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/BackspaceUnindents", b );
}

//const
bool optMannaSettings::backspaceUnindents()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/BackspaceUnindents", true ).toBool();
}

void optMannaSettings::setIndentationGuides( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/IndentationGuides", b );
}

//const
bool optMannaSettings::indentationGuides()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/IndentationGuides", true ).toBool();
}

void optMannaSettings::setIndentationsUseTabs( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/IndentationsUseTabs", b );
}

//const
bool optMannaSettings::indentationsUseTabs()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/IndentationsUseTabs", true ).toBool();
}

void optMannaSettings::setIndentationWidth( int i )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/IndentationWidth", i );
}

//const
int optMannaSettings::indentationWidth()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/IndentationWidth", 4 ).toInt();
}

void optMannaSettings::setTabIndents( bool b )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/TabIndents", b );
}

//const
bool optMannaSettings::tabIndents()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/TabIndents", true ).toBool();
}

void optMannaSettings::setTabWidth( int i )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/TabWidth", i );
}

//const
int optMannaSettings::tabWidth()
{
    return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/TabWidth", 4 ).toInt();
}

void optMannaSettings::setIndentationGuidesBackgroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/IndentationGuidesBackgroundColor", c ); }

const QColor optMannaSettings::indentationGuidesBackgroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/IndentationGuidesBackgroundColor", QColor( "#0000ff" ) ).value<QColor>(); }

void optMannaSettings::setIndentationGuidesForegroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/IndentationGuidesForegroundColor", c ); }

const QColor optMannaSettings::indentationGuidesForegroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/IndentationGuidesForegroundColor", QColor( "#0000ff" ) ).value<QColor>(); }

void optMannaSettings::setBraceMatching( QsciScintilla::BraceMatch b )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/BraceMatching", b ); }

//const
QsciScintilla::BraceMatch optMannaSettings::braceMatching()
{ return (QsciScintilla::BraceMatch)MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/BraceMatching", (int)QsciScintilla::SloppyBraceMatch ).toInt(); }

void optMannaSettings::setMatchedBraceBackgroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/MatchedBraceBackgroundColor", c ); }

const QColor optMannaSettings::matchedBraceBackgroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/MatchedBraceBackgroundColor", QColor( "#ffff7f" ) ).value<QColor>(); }

void optMannaSettings::setMatchedBraceForegroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/MatchedBraceForegroundColor", c ); }

const QColor optMannaSettings::matchedBraceForegroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/MatchedBraceForegroundColor", QColor( "#ff0000" ) ).value<QColor>(); }

void optMannaSettings::setUnmatchedBraceBackgroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/UnmatchedBraceBackgroundColor", c ); }

const QColor optMannaSettings::unmatchedBraceBackgroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/UnmatchedBraceBackgroundColor", QColor( "#55aa00" ) ).value<QColor>(); }

void optMannaSettings::setUnmatchedBraceForegroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/UnmatchedBraceForegroundColor", c ); }

const QColor optMannaSettings::unmatchedBraceForegroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/UnmatchedBraceForegroundColor", QColor( "#ff0000" ) ).value<QColor>(); }

void optMannaSettings::setEdgeMode( QsciScintilla::EdgeMode m )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/EdgeMode", m ); }

//const
QsciScintilla::EdgeMode optMannaSettings::edgeMode()
{ return (QsciScintilla::EdgeMode)MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/EdgeMode", (int)QsciScintilla::EdgeNone ).toInt(); }

void optMannaSettings::setEdgeColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/EdgeColor", c ); }

const QColor optMannaSettings::edgeColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/EdgeColor", QColor( "#ff0000" ) ).value<QColor>(); }

void optMannaSettings::setEdgeColumn( int i )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/EdgeColumn", i ); }

//const
int optMannaSettings::edgeColumn()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/EdgeColumn", 80 ).toInt(); }

void optMannaSettings::setCaretLineVisible( bool b )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/CaretLineVisible", b ); }

//const
bool optMannaSettings::caretLineVisible()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/CaretLineVisible", false ).toBool(); }

void optMannaSettings::setCaretLineBackgroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/CaretLineBackgroundColor", c ); }

const QColor optMannaSettings::caretLineBackgroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/CaretLineBackgroundColor", QColor( "#aaaaff" ) ).value<QColor>(); }

void optMannaSettings::setCaretForegroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/CaretForegroundColor", c ); }

const QColor optMannaSettings::caretForegroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/CaretForegroundColor", QColor( "#000000" ) ).value<QColor>(); }

void optMannaSettings::setCaretWidth( int i )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/CaretWidth", i ); }

//const
int optMannaSettings::caretWidth()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/CaretWidth", 1 ).toInt(); }

void optMannaSettings::setLineNumbersMarginEnabled( bool b )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/LineNumbersMarginEnabled", b ); }

//const
bool optMannaSettings::lineNumbersMarginEnabled()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/LineNumbersMarginEnabled", true ).toBool(); }

void optMannaSettings::setLineNumbersMarginWidth( int i )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/LineNumbersMarginWidth", i ); }

//const
int optMannaSettings::lineNumbersMarginWidth()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/LineNumbersMarginWidth", 4 ).toInt(); }

void optMannaSettings::setLineNumbersMarginAutoWidth( bool b )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/LineNumbersMarginAutoWidth", b ); }

//const
bool optMannaSettings::lineNumbersMarginAutoWidth()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/LineNumbersMarginAutoWidth", true ).toBool(); }

void optMannaSettings::setFolding( QsciScintilla::FoldStyle f )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/Folding", f ); }

//const
QsciScintilla::FoldStyle optMannaSettings::folding()
{ return (QsciScintilla::FoldStyle)MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/Folding", (int)QsciScintilla::BoxedTreeFoldStyle ).toInt(); }

void optMannaSettings::setFoldMarginBackgroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/FoldMarginBackgroundColor", c ); }

const QColor optMannaSettings::foldMarginBackgroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/FoldMarginBackgroundColor", QColor( "#c0c0c0" ) ).value<QColor>(); }

void optMannaSettings::setFoldMarginForegroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/FoldMarginForegroundColor", c ); }

const QColor optMannaSettings::foldMarginForegroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/FoldMarginForegroundColor", QColor( "#000000" ) ).value<QColor>(); }

void optMannaSettings::setMarginsEnabled( bool b )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/MarginsEnabled", b ); }

//const
bool optMannaSettings::marginsEnabled()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/MarginsEnabled", false ).toBool(); }

void optMannaSettings::setMarginsBackgroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/MarginsBackgroundColor", c ); }

const QColor optMannaSettings::marginsBackgroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/MarginsBackgroundColor", QColor( "#c0c0c0" ) ).value<QColor>(); }

void optMannaSettings::setMarginsForegroundColor( const QColor& c )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/MarginsForegroundColor", c ); }

const QColor optMannaSettings::marginsForegroundColor()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/MarginsForegroundColor", QColor( "#000000" ) ).value<QColor>(); }

void optMannaSettings::setMarginsFont( const QFont& f )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/MarginsFont", f.toString() ); }

const QFont optMannaSettings::marginsFont()
{
    QFont f;
    f.fromString( MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/MarginsFont", f.toString() ).toString() );
    return f;
}

//const
QsciScintilla::EolMode optMannaSettings::eolMode()
{
#if defined( Q_OS_WIN )
    int i = QsciScintilla::EolWindows;
#elif defined( Q_WS_MAC )
    int i = QsciScintilla::EolMac;
#else
    int i = QsciScintilla::EolUnix;
#endif
    return (QsciScintilla::EolMode)MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/EolMode", i ).toInt();
}


void optMannaSettings::setEolMode( QsciScintilla::EolMode e )
{
    MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/EolMode", e );
}

QString optMannaSettings::getEol( QsciScintilla::EolMode e )
{
    switch ( e )
    {
        case QsciScintilla::EolWindows:
            return QString( "\r\n" );
            break;
        case QsciScintilla::EolUnix:
            return QString( "\n" );
            break;
        case QsciScintilla::EolMac:
            return QString( "\n" );
            break;
        default:
            return QString( "\r\n" );
    }
}

void optMannaSettings::setEolVisibility( bool b )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/EolVisibility", b ); }

//const
bool optMannaSettings::eolVisibility()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/EolVisibility", false ).toBool(); }

void optMannaSettings::setWhitespaceVisibility( QsciScintilla::WhitespaceVisibility w )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/WhitespaceVisibility", w ); }

//const
QsciScintilla::WhitespaceVisibility optMannaSettings::whitespaceVisibility()
{ return (QsciScintilla::WhitespaceVisibility)MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/WhitespaceVisibility", (int)QsciScintilla::WsInvisible ).toInt(); }

void optMannaSettings::setWrapMode( QsciScintilla::WrapMode w )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/WrapMode", w ); }

//const
QsciScintilla::WrapMode optMannaSettings::wrapMode()
{ return (QsciScintilla::WrapMode)MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/WrapMode", (int)QsciScintilla::WrapNone ).toInt(); }

void optMannaSettings::setWrapVisualFlagsEnabled( bool b )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/WrapVisualFlagsEnabled", b ); }

//const
bool optMannaSettings::wrapVisualFlagsEnabled()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/WrapVisualFlagsEnabled", false ).toBool(); }

void optMannaSettings::setStartWrapVisualFlag( QsciScintilla::WrapVisualFlag f )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/StartWrapVisualFlag", f ); }

//const
QsciScintilla::WrapVisualFlag optMannaSettings::startWrapVisualFlag()
{ return (QsciScintilla::WrapVisualFlag)MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/StartWrapVisualFlag", (int)QsciScintilla::WrapFlagNone ).toInt(); }

void optMannaSettings::setEndWrapVisualFlag( QsciScintilla::WrapVisualFlag f )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/EndWrapVisualFlag", f ); }

//const
QsciScintilla::WrapVisualFlag optMannaSettings::endWrapVisualFlag()
{ return (QsciScintilla::WrapVisualFlag)MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/EndWrapVisualFlag", (int)QsciScintilla::WrapFlagNone ).toInt(); }

void optMannaSettings::setWrappedLineIndentWidth( int i )
{ MannaSettings::getMannaSettings()->setValue( MannaSettings::settingsPath() +"/WrappedLineIndentWidth", i ); }

//const
int optMannaSettings::wrappedLineIndentWidth()
{ return MannaSettings::getMannaSettings()->value( MannaSettings::settingsPath() +"/WrappedLineIndentWidth", 0 ).toInt(); }

void optMannaSettings::setMEditorProperties( MEditor* e )
{
    if ( !e )
        return;
    // General
    e->setSelectionBackgroundColor( selectionBackgroundColor() );
    e->setSelectionForegroundColor( selectionForegroundColor() );
    if ( defaultDocumentColours() ) {
        // set scintilla default colors
        e->setColor( defaultDocumentPen() );
        e->setPaper( defaultDocumentPaper() );
    }
    // Auto Completion
    e->setAutoCompletionCaseSensitivity( autoCompletionCaseSensitivity() );
    e->setAutoCompletionReplaceWord( autoCompletionReplaceWord() );
    e->setAutoCompletionShowSingle( autoCompletionShowSingle() );
    e->setAutoCompletionSource( autoCompletionSource() );
    e->setAutoCompletionThreshold( autoCompletionThreshold() );
    // CallTips
    e->setCallTipsBackgroundColor( callTipsBackgroundColor() );
    e->setCallTipsForegroundColor( callTipsForegroundColor() );
    e->setCallTipsHighlightColor( callTipsHighlightColor() );
    e->setCallTipsStyle( callTipsStyle() );
    e->setCallTipsVisible( callTipsVisible() );
    // Indentation
    e->setAutoIndent(autoIndent());
    e->setBackspaceUnindents( backspaceUnindents() );
    e->setIndentationGuides( indentationGuides() );
    e->setIndentationsUseTabs( indentationsUseTabs() );
    e->setIndentationWidth( indentationWidth() );
    e->setTabIndents( tabIndents() );
    e->setTabWidth( tabWidth() );
    e->setIndentationGuidesBackgroundColor( indentationGuidesBackgroundColor() );
    e->setIndentationGuidesForegroundColor( indentationGuidesForegroundColor() );
    // Brace Matching
    e->setBraceMatching( braceMatching() );
    e->setMatchedBraceBackgroundColor( matchedBraceBackgroundColor() );
    e->setMatchedBraceForegroundColor( matchedBraceForegroundColor() );
    e->setUnmatchedBraceBackgroundColor( unmatchedBraceBackgroundColor() );
    e->setUnmatchedBraceForegroundColor( unmatchedBraceForegroundColor() );
    // Edge Mode
    e->setEdgeMode( edgeMode() );
    e->setEdgeColor( edgeColor() );
    e->setEdgeColumn( edgeColumn() );
    // Caret
    e->setCaretLineVisible( caretLineVisible() );
    e->setCaretLineBackgroundColor( caretLineBackgroundColor() );
    e->setCaretForegroundColor( caretForegroundColor() );
    e->setCaretWidth( caretWidth() );
    // Margins
    if ( marginsEnabled() ) {
        e->setMarginsBackgroundColor( marginsBackgroundColor() );
        e->setMarginsForegroundColor( marginsForegroundColor() );
        e->setMarginsFont( marginsFont() );
    }
    e->setLineNumbersMarginEnabled( lineNumbersMarginEnabled() );
    e->setLineNumbersMarginWidth( lineNumbersMarginWidth() );
    e->setLineNumbersMarginAutoWidth( lineNumbersMarginAutoWidth() );
    e->setFolding( folding() );
    e->setFoldMarginColors( foldMarginForegroundColor(), foldMarginBackgroundColor() );
    // Special Characters
    e->setEolMode( eolMode() );
    e->setEolVisibility( eolVisibility() );
    e->setWhitespaceVisibility( whitespaceVisibility() );
    e->setWrapMode( wrapMode() );
    e->setWrapVisualFlags( endWrapVisualFlag(), startWrapVisualFlag(), wrappedLineIndentWidth() );
}
